#Include <Array.au3>
#Include <Constants.au3>
#Include <File.au3>
#Include <Process.au3>
#Include <String.au3>

$cExtensions   = '*.3gp;*.avi;*.avs;*.divx;*.f4v;*.flac;*.flv;*.m2ts;*.m4v;*.mkv;*.mp3;*.mp4;*.mpg;*.ogg;*.ogm;*.ts;*.vob'
$sBaseLocation = StringLeft( @ScriptDir , StringInStr( @ScriptDir , '\' , 0 , -1 ))

; Select Video Folder
While 1
	$sVideo_Folder = FileSelectFolder( 'Select Video Folder.' , '' , 6 )
	If @Error = 1 AND $sVideo_Folder = '' Then
		MsgBox( 4096 , 'Exit:' , 'Ending Application' )
		Exit
	ElseIf $sVideo_Folder = '' Then
		MsgBox( 4096 , 'Error:' , 'Unable To Open Folder.' )
	ElseIf NOT FileExists ( $sVideo_Folder ) Then
		MsgBox( 4096 , 'Error:' , 'Invalid Folder.' )
	Else
		If StringRight( $sVideo_Folder , 1 ) <> '\' Then $sVideo_Folder &= '\'
		$aAllFiles = _FileListToArrayRec( $sVideo_Folder , $cExtensions , 1 , 1 , 0 , 2 )
		If NOT IsArray( $aAllFiles ) Then
			MsgBox( 4096 , 'Error:' , 'No Files Found.' )
		Else
			_ArraySort( $aAllFiles , 0 , 1 )
			ExitLoop
		EndIf
	EndIf
WEnd

; Create Temp Folder
Global $sTempFolder = @TempDir & '\VideoGain-' & _RandomString() & '\'
If NOT FileExists( $sTempFolder ) Then DirCreate( $sTempFolder )

For $ii = 1 To $aAllFiles[0]
	; Test If File Still Exists
	If NOT FileExists( $aAllFiles[$ii] ) Then ContinueLoop

	; Define Macro's
	$sFileDir    = StringLeft     ( $aAllFiles[$ii] , StringInStr( $aAllFiles[$ii] , '\' , 0 , -1 ) )
	$sFileExt    = StringTrimLeft ( $aAllFiles[$ii] , StringInStr( $aAllFiles[$ii] , '.' , 0 , -1 ) - 1 )
	$sFileName   = StringTrimLeft ( $aAllFiles[$ii] , StringInStr( $aAllFiles[$ii] , '\' , 0 , -1 ) )
	$sShortName  = StringLeft     ( $sFileName , StringInStr( $sFileName , '.' , 0 , -1 ) - 1 )
	$sParent     = StringTrimLeft ( $sFileDir  , StringInStr( $sFileDir  , '\' , 0 , -2 ) )
	$sFolderName = StringTrimRight( StringTrimLeft( $sFileDir , StringInStr( $sFileDir , '\' , 0 , -2 ) ) , 1 )
	$sComplete = $sFileDir & 'Complete\'

	; Skip if Already Completed
	If StringInStr( $aAllFiles[$ii]  , '\Complete\' ) <> 0  Then ContinueLoop
	If FileExists( $sComplete & $sShortName & '.*' ) Then ContinueLoop

	; Clear Strings
	$sFileMP4 = ''

	; Build Array of Streams
	$sRandomString = _RandomString()
	RunWait( @ComSpec & ' /c ffprobe.exe -show_streams "' & $aAllFiles[$ii] & '" >"' & $sTempFolder & $sRandomString & '.txt"' , $sBaseLocation & 'BIN\FFMpeg\' , @SW_HIDE )
	$aAllStreams = _StringBetween( FileRead( $sTempFolder & $sRandomString  & '.txt' ) , '[STREAM]' , '[/STREAM]' )
	FileDelete( $sTempFolder & $sRandomString & '.txt' )

	; Find Video Streams
	$aFindStreams = _ArrayFindAll( $aAllStreams , 'codec_type=video' , 0 , 0 , 0 , 1 )
	If $aFindStreams <> -1 Then
		; Process Video Streams
		For $aa = 0 To UBound( $aFindStreams ) - 1
			$iSVideoIndex	    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?index=(\S+))?'                )
			$sSVideoCodec	    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?codec_name=(\S+))?'           )
			$sSVideoFourCC	    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?codec_tag_string=(\S+))?'     )
			$iSVideoWidth	    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?width=(\S+))?'                )
			$iSVideoHeight	    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?height=(\S+))?'               )
			$fSVideoSAR		    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?sample_aspect_ratio=(\S+))?'  )
			$fSVideoDAR		    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?display_aspect_ratio=(\S+))?' )
			$sSVideoPixel	    = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?pix_fmt=(\S+))?'              )
			$iSVideoNumerator  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?r_frame_rate=(\d+)/)?'        )
			$iSVideoDenominator= _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?r_frame_rate=\d+/(\d+))?'     )
			$sSVideoLanguage   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?language=(\S+))?'             )
			$sSVideoStartTime  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?start_time=(\S+))?'           )
			$iSVideoDuration   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?duration=(\S+))?'             )
			$sSVideoMetaLang   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?TAG:language=(\S+))?'         )
			$sSVideoMetaTitle  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?TAG:title=(\V+))?'            )
			$iSVideoFrames     = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?nb_frames=(\S+))?'            )

			; Reset Meta
			$sMetaMP4 = ''

			; Append Video Language
			If $sSVideoLanguage  <> '' Then $sMetaMP4 &= ':lang="' & $sSVideoLanguage & '"'

			; Append Video Title
			If $sSVideoMetaTitle <> '' Then $sMetaMP4 &= ':name="' & $sSVideoMetaTitle & '"'

			; DeMux Video Stream
			$sRandomString = _RandomString()
			RunWait( @ComSpec & ' /c ffmpeg.exe -i "' & $aAllFiles[$ii] & '" -map 0:' & $iSVideoIndex & ' -c copy -y "' & $sTempFolder & $sRandomString & '.mp4"' , $sBaseLocation & 'BIN\FFMpeg\' , @SW_HIDE )

			; Set Strings
			$sFileMP4 &= ' -add ' & FileGetShortName( $sTempFolder & $sRandomString & '.mp4' ) & ':fps=' & $iSVideoNumerator / $iSVideoDenominator & $sMetaMP4
		Next
	EndIf

	; Find Audio Streams
	$aFindStreams = _ArrayFindAll( $aAllStreams , 'codec_type=audio' , 0 , 0 , 0 , 1 )
	If $aFindStreams <> -1 Then
		; Process Audio Streams
		For $aa = 0 To UBound( $aFindStreams ) - 1
			$iSAudioIndex      = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?index=(\S+))?'        )
			$sSAudioCodec      = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?codec_name=(\S+))?'   )
			$iSAudioSampleRate = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?sample_rate=(\S+))?'  )
			$iSAudioChannels   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?channels=(\S+))?'     )
			$sSAudioLanguage   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?language=(\S+))?'     )
			$sSAudioStartTime  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?start_time=(\S+))?'   )
			$iSAudioDuration   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?duration=(\S+))?'     )
			$sSAudioMetaLang   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?TAG:language=(\S+))?' )
			$sSAudioMetaName   = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?TAG:title=(\V+))?'    )

			; Reset Meta
			$sMetaMP4 = ''

			; Append Audio Language
			If $sSAudioLanguage <> '' Then $sMetaMP4 &= ':lang="' & $sSAudioLanguage  & '"'

			; Append Audio Title
			If $sSAudioMetaName <> '' Then $sMetaMP4 &= ':name="' & $sSAudioMetaName & '"'

			; DeMux Audio Stream
			$sRandomString = _RandomString()
			RunWait( @ComSpec & ' /c ffmpeg.exe -i "' & $aAllFiles[$ii] & '" -map 0:' & $iSAudioIndex & ' -c:a copy "' & $sTempFolder & $sRandomString & '.mp4"' , $sBaseLocation & 'BIN\FFMpeg\' , @SW_HIDE )

			; Set Strings
			$sFileMP4 &= ' -add ' & FileGetShortName( $sTempFolder & $sRandomString & '.mp4' ) & $sMetaMP4
		Next
	EndIf

	; Find SubTitle Streams
	$aFindStreams = _ArrayFindAll( $aAllStreams , 'codec_type=subtitle' , 0 , 0 , 0 , 1 )
	If $aFindStreams <> -1 Then
		; Process SubTitle Streams
		For $aa = 0 To UBound( $aFindStreams ) - 1
			$iSSubtitleIndex     = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?index=(\S+))?'        )
			$sSSubtitleCodec     = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?codec_name=(\S+))?'   )
			$sSSubtitleLanguage  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?language=(\S+))?'     )
			$sSSubtitleStartTime = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?start_time=(\S+))?'   )
			$iSSubtitleDuration  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?duration=(\S+))?'     )
			$sSSubtitleMetaLang  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?TAG:language=(\S+))?' )
			$sSSubtitleMetaName  = _RegExString( $aAllStreams[$aFindStreams[$aa]] , '(?s)(?i)(?:.+?TAG:title=(\V+))?'    )

			; Reset Meta
			$sMetaMP4 = ''

			; Append Subtitle Language
			If $sSSubtitleLanguage <> '' Then $sMetaMP4 &= ':lang="' & $sSSubtitleLanguage & '"'

			; Append Subtitle Title
			If $sSSubtitleMetaName <> '' Then $sMetaMP4 &= ':name="' & $sSSubtitleMetaName & '"'

			; Handle Sub Codec's
			$sRandomString = _RandomString()
			Switch $sSSubtitleCodec
				Case 'ASS' , 'SSA' , 'S_TEXT/ASS' , 'S_TEXT/SSA'
					RunWait( @ComSpec & ' /c ffmpeg.exe -i "' & $aAllFiles[$ii] & '" -map 0:' & $iSSubtitleIndex & ' -c copy -y "' & $sTempFolder & $sRandomString & '.ass"'  , $sBaseLocation & 'BIN\FFMpeg\' , @SW_HIDE )
					RunWait( @ComSpec & ' /c SubtitleWorkshop.exe "/CONVERT(' & $sTempFolder & $sRandomString & '.ass/' & $sTempFolder & $sRandomString & '.srt/SubRip/0/0)"' , $sBaseLocation & 'BIN\Subtitle Workshop\' , @SW_HIDE )
				Case 'SubRip' , 'SRT' , 'S_TEXT/UTF8'
					RunWait( @ComSpec & ' /c ffmpeg.exe -i "' & $aAllFiles[$ii] & '" -map 0:' & $iSSubtitleIndex & ' -c copy -y "' & $sTempFolder & $sRandomString & '.srt"'  , $sBaseLocation & 'BIN\FFMpeg\' , @SW_HIDE )
				Case Else
					Switch $sFileExt
						Case '.mkv'
							RunWait( @ComSpec & ' /c mkvextract.exe tracks "' & $aAllFiles[$ii] & '" ' & $iSSubtitleIndex + 1 & ':"' & $sTempFolder & $sRandomString & '.srt"'  , $sBaseLocation & 'BIN\MKVToolNix\' , @SW_HIDE )
						Case '.mp4' , '.m4v' , '.f4v'
							RunWait( @ComSpec & ' /c MP4Box.exe -srt ' & $iSSubtitleIndex + 1 & ' "' & $aAllFiles[$ii] & '"' , $sBaseLocation & 'BIN\MMP4Box\' , @SW_HIDE )
							FileMove( $sFileDir & $sShortName & '_' & $iSSubtitleIndex + 1 & '_text.srt' , $sTempFolder & $sRandomString & '.srt' , 9 )
					EndSwitch
			EndSwitch
			_Create_SRT( $sTempFolder , $sRandomString , @ScriptDir & '\Banned Words.txt' )

			; Set Strings
			$sFileMP4 &= ' -add ' & FileGetShortName( $sTempFolder & $sRandomString & '.srt' ) & $sMetaMP4
		Next
	EndIf

	; Merge Files
	$sRandomString = _RandomString()
	RunWait( @ComSpec & ' /c mp4box.exe' & $sFileMP4 & ' -new "' & $sTempFolder & $sRandomString & '.mp4"' , $sBaseLocation & 'BIN\MP4Box\' , @SW_HIDE )

	; Move to Final Destination
	FileMove( $sTempFolder & $sRandomString & '.mp4' , $sComplete & $sShortName & '.mp4' , 9 )

	; Clean Temp Folder
	FileDelete( $sTempFolder )
Next
; Remove Temp Folder
DirRemove( $sTempFolder , 1 )

MsgBox ( 0 , 'Finished' , 'Batch Operation Complete' )



Func _RegExString( $sString , $sRegEx )
	Return _ArrayToString( StringRegExp( $sString , $sRegEx , 1 ))
EndFunc

Func _RandomString()
	$sString = ''
	Dim $aSpace[3]
	For $i = 1 To 15
		$aSpace[0] = Chr( Random( 65 ,  90 , 1 )) ; A-Z
		$aSpace[1] = Chr( Random( 97 , 122 , 1 )) ; a-z
		$aSpace[2] = Chr( Random( 48 ,  57 , 1 )) ; 0-9
		$sString &= $aSpace[Random( 0 , 2 , 1 )]
	Next
	Return $sString
EndFunc

Func _Create_SRT( $sInFolder , $sInName , $sBanFile )
	$sRandomString1 = _RandomString()
	$sRandomString2 = _RandomString()
	$sInFile = $sInFolder & $sInName & '.srt'
	FileMove( $sInFile , $sInFolder & $sRandomString1 & '.srt' , 9 )
	RunWait( @ComSpec & ' /c SubtitleWorkshop.exe "/CONVERT(' & $sInFolder & $sRandomString1 & '.srt/' & $sInFolder & $sRandomString2 & '.srt/SubRip/0/0)"' , $sBaseLocation & 'BIN\Subtitle Workshop\' , @SW_HIDE )
	RunWait( @ComSpec & ' /c SubtitleWorkshop.exe "/CONVERT(' & $sInFolder & $sRandomString2 & '.srt/' & $sInFolder & $sInName        & '.srt/SubRip/0/0)"' , $sBaseLocation & 'BIN\Subtitle Workshop\' , @SW_HIDE )
	FileDelete( $sInFolder & $sRandomString1 & '.srt' )
	FileDelete( $sInFolder & $sRandomString2 & '.srt' )

	Dim $aBannedWords
	If FileExists( $sBanFile ) Then _FileReadToArray( $sBanFile , $aBannedWords )
	$sFile = FileOpen( $sInFile , 0 )
	If NOT @Error AND IsArray( $aBannedWords ) Then
		Dim $aSections[1][2]=[[0]]
		While 1
			$sLine = FileReadLine( $sFile )
			If @Error = -1 Then ExitLoop
			$aSection = StringRegExp( $sLine , '(?i)(\d\d:\d\d:\d\d,\d\d\d --> \d\d:\d\d:\d\d,\d\d\d)' , 1 )
			If @Error Then ContinueLoop
			$sTime = $aSection[0]
			$sString = ''
			While 1
				$sLine = FileReadLine( $sFile )
				If @Error = -1 Then ExitLoop 2
				If $sLine = '' Then
					For $ii = 1 To $aBannedWords[0]
						If StringInStr( $sString , $aBannedWords[$ii] ) <> 0 Then
							ContinueLoop 3
						EndIf
					Next
					$iCount = UBound( $aSections )
					ReDim $aSections[$iCount + 1][2]
					$aSections[0][0] = $iCount
					$aSections[$iCount][0] = $sTime & @CRLF
					$aSections[$iCount][1] = $sString
					ExitLoop
				EndIf
				$sString &= $sLine & @CRLF
			WEnd
		WEnd
		FileClose( $sFile )
	EndIf

	If IsDeclared( 'aSections' ) then
		$sNewFile = ''
		For $ii = 1 To $aSections[0][0]
			$sNewFile &= $ii & @CRLF
			$sNewFile &= $aSections[$ii][0]
			$sNewFile &= $aSections[$ii][1]
			$sNewFile &= @CRLF
		Next
		FileDelete( $sInFile )
		$sFile = FileOpen(   $sInFile , 138 )
		FileWrite(  $sFile , $sNewFile )
		FileClose( $sFile )
	EndIf
EndFunc
